package com.tbit.main.controller.interceptor;

import com.tbit.common.utils.TraceUtil;
import com.tbit.main.common.JsonResult;
import com.tbit.main.constant.ResponseCode;
import com.tbit.main.exception.BaseException;
import com.tbit.main.exception.BaseExceptionContent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.support.RequestContext;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

/**
 * 异常拦截
 *
 * @author Leon
 * 2019年1月23日 下午3:51:31
 */
@ResponseBody
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 自定义异常
     */
    @ExceptionHandler(value = {BaseException.class})
    public JsonResult<?> handleBaseException(BaseException e, HttpServletRequest request) {
        log.warn("自定义异常,接口地址:{},异常信息:{}", request.getRequestURI(), e.getMessage());
        RequestContext requestContext = new RequestContext(request);

        return JsonResult.fail(null, requestContext.getMessage(e.getMsg()), TraceUtil.getTraceIdByLocal());
    }

    /**
     * 自定义异常内容
     */
    @ExceptionHandler(value = {BaseExceptionContent.class})
    public JsonResult<?> handleBaseExceptionContent(BaseExceptionContent e, HttpServletRequest request) {
        log.warn("自定义异常内容,接口地址:{},异常信息:{}", request.getRequestURI(), e.getMessage(), e);
        RequestContext requestContext = new RequestContext(request);

        return JsonResult.failContent(null, requestContext.getMessage(e.getMsg()), e.getContent(), TraceUtil.getTraceIdByLocal());
    }

    /**
     * 处理其他异常，记录到日志
     */
    @ExceptionHandler(value = Exception.class)
    public JsonResult<?> handleOtherException(HttpServletRequest req, Throwable ex) {
        RequestContext requestContext = new RequestContext(req);
        log.error("服务器异常,接口地址:{},异常信息:{}", req.getRequestURI(), ex.getMessage(), ex);
        return JsonResult.fail(ResponseCode.FAIL_CODE, requestContext.getMessage("System.error"), TraceUtil.getTraceIdByLocal());
    }

    /**
     * 处理 SpringMVC 参数绑定不正确，本质上也是通过 Validator 校验
     */
    @ExceptionHandler(value = {BindException.class})
    public JsonResult<?> handleBindException(HttpServletRequest request, BindException ex) {
        log.warn("参数绑定异常,接口地址:{},异常信息:{}", request.getRequestURI(), ex.getMessage());
        RequestContext requestContext = new RequestContext(request);
        String errorMessage = Optional.ofNullable(ex.getFieldError()).map(FieldError::getDefaultMessage).orElse("System.error");
        return JsonResult.fail(null, requestContext.getMessage(errorMessage), TraceUtil.getTraceIdByLocal());
    }

}
